﻿using log4net;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;


namespace TcpServer.Facade
{
    /// <summary>
    /// 缓存类，缓存信息、客户端连接
    /// </summary>
    public class BufferFacade
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(BufferFacade));

        //接收服务器
        public static HPSocketCS.TcpServer Server = new HPSocketCS.TcpServer();
        /// <summary>
        /// 消息队列-持久化
        /// </summary>
        public static ConcurrentQueue<SocketClientInfo> MessageQueue4Persistence = new ConcurrentQueue<SocketClientInfo>();
        /// <summary>
        /// 消息队列-业务处理
        /// </summary>
        public static ConcurrentQueue<SocketClientInfo> MessageQueue4BizProcess = new ConcurrentQueue<SocketClientInfo>();
        /// <summary>
        ///  客户端缓存
        /// </summary>
        private static readonly ConcurrentDictionary<IntPtr, string> Connections = new ConcurrentDictionary<IntPtr, string>();
        /// <summary>
        /// 根据持久化还是业务处理添加消息到相应的消息队列
        /// </summary>
        /// <param name="type">持久化或业务处理</param>
        /// <param name="msg">消息</param>
        public static void EnqueueToMessageQueue(QueueType type, SocketClientInfo msg)
        {
            log.Debug( "接收到消息:" + msg.ReceivedMsg);
            switch (type)
            {
                case QueueType.Persistence:
                    MessageQueue4Persistence.Enqueue(msg);
                    break;
                case QueueType.BizProcess:
                    MessageQueue4BizProcess.Enqueue(msg);
                    break;
                case QueueType.Both:
                    MessageQueue4Persistence.Enqueue(msg);
                    MessageQueue4BizProcess.Enqueue(msg);
                    break;
            }
        }
        /// <summary>
        /// 根据持久化还是业务处理从相应的消息队列获得消息
        /// </summary>
        /// <param name="type">持久化或业务处理</param>
        public static SocketClientInfo DequeueFromMessageQueue(QueueType type)
        {
            SocketClientInfo result = null;
            switch (type)
            {
                case QueueType.Persistence:
                    MessageQueue4Persistence.TryDequeue(out result);
                    break;
                case QueueType.BizProcess:
                    MessageQueue4BizProcess.TryDequeue(out result);
                    break;
                case QueueType.Both:
                    throw new Exception("不能是Both,不能同时从两个队列弹出信息");
            }
            return result;
        }

        public static void AddSocket(IntPtr connId, string mn)
        {
            try
            {
                Connections.TryAdd(connId, mn);
            }
            catch (Exception ex)
            {
                log.Error( ex);
            }
        }

        public static string RemoveSocket(IntPtr connId)
        {
            string mn = null;
            try
            {
                Connections.TryRemove(connId, out mn);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
            return mn;
        }

        public static int ConnectionsCount()
        {
            return Connections.Count;
        }

        public static List<IntPtr> GetSocket(string mn)
        {
            List<IntPtr> list = new List<IntPtr>();
            try
            {
                var items = Connections.Where(t => t.Value == mn);
                list.AddRange(items.Select(item => item.Key));
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
            return list;
        }

        public static List<string> GetMNs()
        {
            try
            {
                return Connections.Select(t => t.Value).Distinct().ToList();
            }
            catch (Exception ex)
            {
                log.Error( ex);
            }
            return null;
        }

        public static Dictionary<IntPtr, string> GetAllSockets()
        {
            try
            {
                return Connections.ToDictionary(k => k.Key, v => v.Value);
            }
            catch (Exception ex)
            {
                log.Error( ex);
            }
            return null;
        }
    }

    public enum QueueType
    {
        Both,
        Persistence,
        BizProcess
    }
    public class SocketClientInfo
    {
        public IntPtr ConnId { get; set; }
        public string IpAddress { get; set; }
        public ushort Port { get; set; }
        public DateTime LogonTime { get; set; }
        public string ReceivedMsg { get; set; }
        // ReSharper disable once InconsistentNaming
        public string MN { get; set; }
    }
}
